﻿using AdvancedREI.Net.Http.Compression;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Text;
using System.Threading.Tasks;

namespace HttpClientPoxy
{
    public class Client
    {
        private static Client client;
        public static Client GetInstance()
        {
            if (client == null)
            {
                client = new Client();
            }
            return client;
        }

        public string ToJson<T>(T obj)
        {
            return JsonConvert.SerializeObject(obj);
        }

        public T FromJson<T>(string json)
        {
            return JsonConvert.DeserializeObject<T>(json);
        }


            //        //下载文件
            //Task<Stream> integerTask = HttpClientPoxy.Client.GetInstance().DownloadFile("http://localhost:8089/api/report/file/R_zxcasd.frx", "");
            //var result = await integerTask;
            //FileStream fileStream = File.Create(System.Environment.GetFolderPath(Environment.SpecialFolder.DesktopDirectory) + "\\R_zxcasd.frx", (int)result.Length);
            //byte[] bytesInStream = new byte[result.Length];
            //result.Read(bytesInStream, 0, bytesInStream.Length);
            //fileStream.Write(bytesInStream, 0, bytesInStream.Length);
            //fileStream.Close();
        public async Task<Stream> DownloadFile(string url, string ukey)
        {
            using (var client = new HttpClient())
            {
                new Uri(new System.Uri(url).GetLeftPart(UriPartial.Authority));
                client.DefaultRequestHeaders.Accept.Clear();
                client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
                client.DefaultRequestHeaders.Add("U-ApiKey", ukey);
                HttpResponseMessage response = await client.GetAsync(url);
                if (response.IsSuccessStatusCode)
                {
                    var result = await response.Content.ReadAsStreamAsync();
                    return result;
                }
                return null;
            }
        }

        //用法
        //async void uploadFile()
        //{
        //    Stream myStream = null;
        //    OpenFileDialog openFileDialog1 = new OpenFileDialog();

        //    openFileDialog1.InitialDirectory = System.Environment.GetFolderPath(Environment.SpecialFolder.Desktop);
        //    openFileDialog1.Filter = "frx files (*.frx)|*.frx|All files (*.*)|*.*";
        //    openFileDialog1.FilterIndex = 2;
        //    openFileDialog1.RestoreDirectory = true;
        //    openFileDialog1.Multiselect = false;

        //    if (openFileDialog1.ShowDialog() == DialogResult.OK)
        //    {
        //        try
        //        {
        //            if ((myStream = openFileDialog1.OpenFile()) != null)
        //            {
        //                var client = new HttpClientPoxy.Client();
        //                string filefullname = Path.GetFileName(openFileDialog1.FileName);
        //                using (myStream)
        //                {
        //                    var d = await client.UploadFile("http://localhost:8089/api/report/fileupload/" + filefullname, "", ReadFully(myStream), filefullname);

        //                }
        //            }
        //        }
        //        catch (Exception ex)
        //        {
        //            MessageBox.Show("Error: Could not read file from disk. Original error: " + ex.Message);
        //        }
        //    }
        //}

        //public byte[] ReadFully(Stream input)
        //{
        //    byte[] buffer = new byte[16 * 1024];
        //    using (MemoryStream ms = new MemoryStream())
        //    {
        //        int read;
        //        while ((read = input.Read(buffer, 0, buffer.Length)) > 0)
        //        {
        //            ms.Write(buffer, 0, read);
        //        }
        //        return ms.ToArray();
        //    }
        //}
        public async Task<string> UploadFile(string url, string ukey, byte[] fileConent, string fileName)
        {
            using (var client = new HttpClient())
            {
                client.BaseAddress = new Uri(new System.Uri(url).GetLeftPart(UriPartial.Authority));
                client.DefaultRequestHeaders.Accept.Clear();
                client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
                client.DefaultRequestHeaders.Add("U-ApiKey", ukey);
                using (var content = new MultipartFormDataContent("Upload----" + DateTime.Now.ToString(CultureInfo.InvariantCulture)))
                {
                    content.Add(new StreamContent(new MemoryStream(fileConent)), Path.GetFileNameWithoutExtension(fileName), fileName);
                    using (var message = await client.PostAsync(url, content))
                    {
                        var input = await message.Content.ReadAsStringAsync();
                        return input;
                    }
                }
            }
        }

        public async Task<string> Upload(string url, List<string> files)
        {
            var message = new HttpRequestMessage();
            var content = new MultipartFormDataContent();
            foreach (var file in files)
            {
                var filestream = new FileStream(file, FileMode.Open);
                var fileName = Path.GetFileName(file);
                content.Add(new StreamContent(filestream), "file", fileName);
            }
            message.Method = HttpMethod.Post;
            message.Content = content;
            message.RequestUri = new Uri(url);

            var client = new HttpClient();
            using (var response = await client.SendAsync(message))
            {
                return await response.Content.ReadAsStringAsync();
            }
        }

        public async Task<string> GetByBasicAuth(string url, string username, string password, bool RsaEncode, bool Compressed)
        {
            string credentials = string.Empty;
            if (RsaEncode)
            {
                credentials = RsaComputer.GetComputer().Encode(string.Format("{0}:{1}", username, password));
            }
            else
            {
                credentials = Convert.ToBase64String(Encoding.UTF8.GetBytes(string.Format("{0}:{1}", username, password)));
            }
            if (Compressed)
            {
                using (var client = new HttpClient(new CompressedHttpClientHandler()))
                {
                    new Uri(new System.Uri(url).GetLeftPart(UriPartial.Authority));
                    client.DefaultRequestHeaders.Accept.Clear();
                    client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
                    client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Basic", credentials);
                    HttpResponseMessage response = await client.GetAsync(url);
                    if (response.IsSuccessStatusCode)
                    {
                        var result = await response.Content.ReadAsAsync<dynamic>();
                        return Convert.ToString(result);
                    }
                    return string.Empty;
                }
            }
            else
            {
                using (var client = new HttpClient())
                {
                    new Uri(new System.Uri(url).GetLeftPart(UriPartial.Authority));
                    client.DefaultRequestHeaders.Accept.Clear();
                    client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
                    client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Basic", credentials);
                    HttpResponseMessage response = await client.GetAsync(url);
                    if (response.IsSuccessStatusCode)
                    {
                        var result = await response.Content.ReadAsAsync<dynamic>();
                        return Convert.ToString(result);
                    }
                    return string.Empty;
                }
            }
        }

        public async Task<string> DeleteByBasicAuth(string url, string username, string password)
        {
            var credentials = Convert.ToBase64String(Encoding.UTF8.GetBytes(string.Format("{0}:{1}", username, password)));
            using (var client = new HttpClient())
            {
                new Uri(new System.Uri(url).GetLeftPart(UriPartial.Authority));
                client.DefaultRequestHeaders.Accept.Clear();
                client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
                client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Basic", credentials);
                HttpResponseMessage response = await client.DeleteAsync(url);
                if (response.IsSuccessStatusCode)
                {
                    var result = await response.Content.ReadAsAsync<dynamic>();
                    return Convert.ToString(result);
                }
                return string.Empty;
            }
        }

        public async Task<string> PostByBasicAuth<T>(string url, string username, string password, T obj)
        {
            var credentials = Convert.ToBase64String(Encoding.UTF8.GetBytes(string.Format("{0}:{1}", username, password)));
            using (var client = new HttpClient())
            {
                client.BaseAddress = new Uri(new System.Uri(url).GetLeftPart(UriPartial.Authority));
                client.DefaultRequestHeaders.Accept.Clear();
                client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
                client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Basic", credentials);
                var response = await client.PostAsJsonAsync(url, obj);
                if (response.IsSuccessStatusCode)
                {
                    //return response.StatusCode.ToString();
                }
                return response.StatusCode.ToString();
            }
        }

        public async Task<string> PostStringByBasicAuth(string url, string username, string password, string obj)
        {
            var credentials = Convert.ToBase64String(Encoding.UTF8.GetBytes(string.Format("{0}:{1}", username, password)));
            using (var client = new HttpClient())
            {
                client.BaseAddress = new Uri(new System.Uri(url).GetLeftPart(UriPartial.Authority));
                client.DefaultRequestHeaders.Accept.Clear();
                client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
                client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Basic", credentials);
                var response = await client.PostAsync(url, new StringContent(obj, Encoding.UTF8, "text/plain"));
                if (response.IsSuccessStatusCode)
                {
                    //return response.StatusCode.ToString();
                }
                return response.StatusCode.ToString();
            }
        }

        public async Task<string> PutByBasicAuth<T>(string url, string username, string password, T obj)
        {
            var credentials = Convert.ToBase64String(Encoding.UTF8.GetBytes(string.Format("{0}:{1}", username, password)));
            using (var client = new HttpClient())
            {
                new Uri(new System.Uri(url).GetLeftPart(UriPartial.Authority));
                client.DefaultRequestHeaders.Accept.Clear();
                client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
                client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Basic", credentials);
                var response = await client.PutAsJsonAsync(url, obj);
                if (response.IsSuccessStatusCode)
                {
                    //return response.StatusCode.ToString();
                }
                return response.StatusCode.ToString();
            }
        }

        public async Task<string> Get(string url, string ukey, bool Compressed)
        {
            if (Compressed)
            {
                using (var client = new HttpClient(new CompressedHttpClientHandler()))
                {
                    new Uri(new System.Uri(url).GetLeftPart(UriPartial.Authority));
                    client.DefaultRequestHeaders.Accept.Clear();
                    client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
                    client.DefaultRequestHeaders.Add("U-ApiKey", ukey);
                    HttpResponseMessage response = await client.GetAsync(url);
                    if (response.IsSuccessStatusCode)
                    {
                        var result = await response.Content.ReadAsAsync<dynamic>();
                        return Convert.ToString(result);
                    }
                    return string.Empty;
                }
            }
            else
            {
                using (var client = new HttpClient())
                {
                    new Uri(new System.Uri(url).GetLeftPart(UriPartial.Authority));
                    client.DefaultRequestHeaders.Accept.Clear();
                    client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
                    client.DefaultRequestHeaders.Add("U-ApiKey", ukey);
                    HttpResponseMessage response = await client.GetAsync(url);
                    if (response.IsSuccessStatusCode)
                    {
                        var result = await response.Content.ReadAsAsync<dynamic>();
                        return Convert.ToString(result);
                    }
                    return string.Empty;
                }
            }
        }

        public async Task<string> Delete(string url, string ukey)
        {
            using (var client = new HttpClient())
            {
                new Uri(new System.Uri(url).GetLeftPart(UriPartial.Authority));
                client.DefaultRequestHeaders.Accept.Clear();
                client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
                client.DefaultRequestHeaders.Add("U-ApiKey", ukey);
                HttpResponseMessage response = await client.DeleteAsync(url);
                if (response.IsSuccessStatusCode)
                {
                    var result = await response.Content.ReadAsAsync<dynamic>();
                    return Convert.ToString(result);
                }
                return string.Empty;
            }
        }

        public async Task<string> Post<T>(string url, string ukey, T obj)
        {
            using (var client = new HttpClient())
            {
                client.BaseAddress = new Uri(new System.Uri(url).GetLeftPart(UriPartial.Authority));
                client.DefaultRequestHeaders.Accept.Clear();
                client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
                client.DefaultRequestHeaders.Add("U-ApiKey", ukey);
                var response = await client.PostAsJsonAsync(url, obj);
                if (response.IsSuccessStatusCode)
                {
                    //return response.StatusCode.ToString();
                }
                return response.StatusCode.ToString();
            }
        }
        
        public async Task<string> PostString(string url, string ukey, string obj)
        {
            using (var client = new HttpClient())
            {
                client.BaseAddress = new Uri(new System.Uri(url).GetLeftPart(UriPartial.Authority));
                client.DefaultRequestHeaders.Accept.Clear();
                client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
                client.DefaultRequestHeaders.Add("U-ApiKey", ukey);
                var response = await client.PostAsync(url, new StringContent(obj, Encoding.UTF8, "text/plain"));
                if (response.IsSuccessStatusCode)
                {
                    //return response.StatusCode.ToString();
                }
                return response.StatusCode.ToString();
            }
        }

        public async Task<string> Put<T>(string url, string ukey, T obj)
        {
            using (var client = new HttpClient())
            {
                new Uri(new System.Uri(url).GetLeftPart(UriPartial.Authority));
                client.DefaultRequestHeaders.Accept.Clear();
                client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
                client.DefaultRequestHeaders.Add("U-ApiKey", ukey);
                var response = await client.PutAsJsonAsync(url, obj);
                if (response.IsSuccessStatusCode)
                {
                    //return response.StatusCode.ToString();
                }
                return response.StatusCode.ToString();
            }
        }

    }
    public class Book
    {
        public string Title { get; set; }
        public DateTime ReleaseDate { get; set; }
        public string Genre { get; set; }
        public decimal Price { get; set; }
    }
}
